package cn.itrip.biz.service.itripHotelOrder;
import cn.itrip.biz.service.itripOrderLinkUser.ItripOrderLinkUserService;
import cn.itrip.dto.Dto;
import cn.itrip.mapper.ItripHotel.ItripHotelMapper;
import cn.itrip.mapper.ItripHotelOrder.ItripHotelOrderMapper;
import cn.itrip.mapper.ItripHotelRoom.ItripHotelRoomMapper;
import cn.itrip.mapper.ItripOrderLinkUser.ItripOrderLinkUserMapper;
import cn.itrip.pojo.*;
import cn.itrip.common.*;
import cn.itrip.vo.order.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import cn.itrip.common.Constants;
import java.math.BigDecimal;

@Service
public class ItripHotelOrderServiceImpl implements ItripHotelOrderService {

    @Resource
    private ItripHotelMapper itripHotelMapper;
    @Resource
    private ItripHotelRoomMapper itripHotelRoomMapper;
    @Resource
    private ItripHotelOrderMapper itripHotelOrderMapper;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private ItripOrderLinkUserMapper itripOrderLinkUserMapper;


    @Override
    public ItripHotelOrder getItripHotelOrderById(Long id) throws Exception {
        return itripHotelOrderMapper.getItripHotelOrderById(id);
    }

    @Override
    public ItripPersonalHotelOrderVO getItripHotelOrderById2(Long id)throws Exception{
        ItripPersonalHotelOrderVO vo=new ItripPersonalHotelOrderVO();
        ItripHotelOrder order = itripHotelOrderMapper.getItripHotelOrderById(id);

        vo.setId(order.getId());
        vo.setOrderNo(order.getOrderNo());
        vo.setOrderStatus(order.getOrderStatus());
        vo.setPayAmount(BigDecimal.valueOf(order.getPayAmount()));
        vo.setPayType(order.getPayType());
        vo.setCreationDate(order.getCreationDate());
        vo.setBookType(order.getBookType());
        ItripHotelRoom room = itripHotelRoomMapper.getItripHotelRoomById(order.getRoomId());
        vo.setRoomPayType(room.getPayType());
        Map map=new HashMap();
        map.put("1","订单提交");
        map.put("2","订单支付");
        map.put("3","支付成功");
        map.put("4","入住");
        map.put("5","订单完成");
        vo.setOrderProcess(map);
        Integer processNode=order.getOrderStatus()+1;
        vo.setProcessNode(processNode.toString());
        vo.setNoticePhone(order.getNoticePhone());
        return vo;
    }

    @Override
    public ItripPersonalOrderRoomVO getItripHotelOrderByVo(Long id) throws Exception {
        return itripHotelOrderMapper.getItripHotelOrderByVo(id);
    }

    @Override
    public List<ItripHotelOrder> getItripHotelOrderByIdAndStatus(Integer userId) throws Exception {
        return itripHotelOrderMapper.getItripHotelOrderByIdAndStatus(userId);
    }

    public static Map<?, ?> objectToMap(Object obj) {
        if(obj == null)
            return null;
        return new org.apache.commons.beanutils.BeanMap(obj);
    }

    public Page getItripHotelOrderListByMap(ItripSearchOrderVO vo)throws Exception{
        //封装前端需要的订单实体类
        //Map<String,String> describe = BeanUtils.describe(vo);
        //分页 当前也
        Integer pageNo = Constants.DEFAULT_PAGE_NO;
        if (EmptyUtils.isNotEmpty(vo.getPageNo())){
            pageNo=vo.getPageNo();
        }
        //显示条数
        Integer pageSize = Constants.DEFAULT_PAGE_SIZE;
        if (EmptyUtils.isNotEmpty(vo.getPageSize())){
            pageSize=vo.getPageSize();
        }

        vo.setPageNo(pageNo);
        vo.setPageSize(pageSize);


        List<ItripHotelOrder> orderlist = itripHotelOrderMapper.getItripHotelOrderList(vo);

        vo.setPageNo(-1);
        vo.setPageSize(-1);

        List<ItripHotelOrder> count = itripHotelOrderMapper.getItripHotelOrderList(vo);


        List<ItripListHotelOrderVO> itripListHotelOrderVO=new ArrayList<>();

        for (ItripHotelOrder order : orderlist) {
            ItripListHotelOrderVO orderVo=new ItripListHotelOrderVO();
            BeanUtils.copyProperties(orderVo,order);
            itripListHotelOrderVO.add(orderVo);
        }



        Page page=new Page(pageNo,pageSize,count.size());
        page.setRows(itripListHotelOrderVO);
        return page;
    }

    //生成订单
    @Override
    public Dto itriptxInsertItripHotelOrder(ItripAddHotelOrderVO vo, String token) throws Exception {
        //校验库存
        HashMap<String,Object> param = new HashMap();
        param.put("startTime",vo.getCheckInDate());
        param.put("endTime",vo.getCheckOutDate());
        param.put("roomId",vo.getRoomId());
        param.put("hotelId",vo.getHotelId());

        List<ItripHotelTempStore> stores = this.queryRoomStore(param);
        if(EmptyUtils.isEmpty(stores)){
            return DtoUtil.returnFail("库存不足","100507 ");
        }

        //转换实体类
        ItripHotelOrder order = new ItripHotelOrder();
        BeanUtils.copyProperties(order,vo);


        //未导入的数据
        //1.用户id，创建人    2.订单号   3.交易编号  4.预订天数  5.订单状态  6.支付金额  7.支付方式  8.入住人名称     9.客户端设备信息   10，预定时间，修改时间，完成时间

        //下单用户id
        String user=redisUtils.getValue(token);
        ItripUser itripUser=JSONObject.parseObject(user,ItripUser.class);
        order.setUserId(itripUser.getId());
        order.setCreatedBy(itripUser.getId());

        //设备类型
        if(token.startsWith("token:PC")){
            order.setBookType(0);
        }else if (token.startsWith("token:MOBILE")){
            order.setBookType(1);
        }else{
            order.setBookType(2);
        }

        //入住人名称
        List<ItripUserLinkUser> linkUser = vo.getLinkUser();
        if (EmptyUtils.isNotEmpty(linkUser)){
            StringBuffer sb = new StringBuffer();
            for (int i=0;;){
                sb.append(linkUser.get(i).getLinkUserName());
                if(++i<linkUser.size()){
                    sb.append(",");
                    continue;
                }
                break;
            }
            order.setLinkUserName(sb.toString());
        }
        //支付方式
        ItripHotelRoom room = itripHotelRoomMapper.getItripHotelRoomById(vo.getRoomId());
        order.setPayType(room.getPayType());

        //订单状态
        order.setOrderStatus(0);

        //预订天数
        long days=DateUtil.getBetweenDates(vo.getCheckInDate(),vo.getCheckOutDate()).size()-1;
        order.setBookingDays((int)days);

        //支付金额
        double money = this.getSumRoomPrice(days*vo.getCount(),room.getRoomPrice());
        order.setPayAmount(money);

        //订单号 日期+机器码+md5(hotelId+roomId+时间+随机数)
        StringBuffer  md5 = new StringBuffer();
        md5.append(vo.getHotelId());
        md5.append(vo.getRoomId());
        md5.append(System.currentTimeMillis());
        md5.append(Math.random()*100000);
        String sb_md5 = MD5.getMd5(md5.toString(),6);
        order.setOrderNo("Y999999"+sb_md5);

        //添加订单
        Map<String,Object> output = this.insertItripHotelOrder(order,vo.getLinkUser());
        return DtoUtil.returnDataSuccess(output);

    }

    /**
     * 计算金额
     * @param count
     * @param roomPrice
     * @return
     * @throws Exception
     */
    @Override
    public double getSumRoomPrice(long count, Double roomPrice) throws Exception {

        // 1. 数量    2.金额    3.以什么方式计算   4.小数点   5.精确度
        BigDecimal money = BigDecimalUtil.OperationASMD(count, roomPrice,
                BigDecimalUtil.BigDecimalOprations.multiply, 2, BigDecimal.ROUND_DOWN);
        return money.doubleValue();
    }

    /**
     * 添加订单和入住人的信息
     * @param order
     * @param linkUsers
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> insertItripHotelOrder(ItripHotelOrder order, List<ItripUserLinkUser> linkUsers) throws Exception {
        //新增订单
        if(EmptyUtils.isEmpty(order.getId())){
            //添加订单创建时间
            order.setCreationDate(new Date());
            itripHotelOrderMapper.insertItripHotelOrder(order);
            //重新获取订单
            ItripHotelOrder itripOrder = itripHotelOrderMapper.getItripHotelOrderIdByOrderno(order.getOrderNo());
            order.setId(itripOrder.getId());
        }else{
            //修改订单
            //删除订单之前的所有联系人
            itripOrderLinkUserMapper.deleteItripOrderLinkUserByOrderId(order.getId());
            itripHotelOrderMapper.updateItripHotelOrder(order);
        }
        //添加联系人
        if(EmptyUtils.isNotEmpty(linkUsers)){
            for (ItripUserLinkUser linkUser:linkUsers){
                //联系人实体类
                ItripOrderLinkUser orderUser = new ItripOrderLinkUser();
                //通过BeanUtils转换
                BeanUtils.copyProperties(orderUser,linkUser);
                //创建时间
                orderUser.setCreationDate(new Date());
                //创建人
                orderUser.setCreatedBy(order.getCreatedBy());
                //插入订单id
                orderUser.setOrderId(order.getId());
                //插入联系人id
                orderUser.setLinkUserId(order.getUserId());
                //插入联系人
                itripOrderLinkUserMapper.insertItripOrderLinkUser(orderUser);
            }
        }
        //返回订单号和订单id
        Map<String,Object> output = new HashMap<>();
        output.put("orderNo",order.getOrderNo());
        output.put("id",order.getId());
        return output;
    }

    @Override
    public ItripPersonalOrderRoomVO getItripPersonalOrderRoomByVo(Long id) throws Exception {
        return itripHotelOrderMapper.getItripPersonalOrderRoomByVo(id);
    }

    @Override
    public Integer changeOrderToComment() throws Exception {
        return itripHotelOrderMapper.changeOrderToComment();
    }

    public Integer getItripHotelOrderCountByMap(Map<String,Object> param)throws Exception{
        return itripHotelOrderMapper.getItripHotelOrderCountByMap(param);
    }

    public Integer itriptxAddItripHotelOrder(ItripHotelOrder itripHotelOrder)throws Exception{
            itripHotelOrder.setCreationDate(new Date());
            return itripHotelOrderMapper.insertItripHotelOrder(itripHotelOrder);
    }

    public Integer itriptxModifyItripHotelOrder(ItripHotelOrder itripHotelOrder)throws Exception{
        itripHotelOrder.setModifyDate(new Date());
        return itripHotelOrderMapper.updateItripHotelOrder(itripHotelOrder);
    }

    public Integer itriptxDeleteItripHotelOrderById(Long id)throws Exception{
        return itripHotelOrderMapper.deleteItripHotelOrderById(id);
    }

    public Page<ItripHotelOrder> queryItripHotelOrderPageByMap(Map<String,Object> param,Integer pageNo,Integer pageSize)throws Exception{
        Integer total = itripHotelOrderMapper.getItripHotelOrderCountByMap(param);
        pageNo = EmptyUtils.isEmpty(pageNo) ? Constants.DEFAULT_PAGE_NO : pageNo;
        pageSize = EmptyUtils.isEmpty(pageSize) ? Constants.DEFAULT_PAGE_SIZE : pageSize;
        Page page = new Page(pageNo, pageSize, total);
        param.put("beginPos", page.getBeginPos());
        param.put("pageSize", page.getPageSize());
        List<ItripHotelOrder> itripHotelOrderList = itripHotelOrderMapper.getItripHotelOrderListByMap(param);
        page.setRows(itripHotelOrderList);
        return page;
    }

    /**
     * 获取预定前信息
     * @param vo
     * @return
     */
    @Override
    public Dto getValiDateRoomStore(ValidateRoomStoreVO vo)throws Exception{
        //根据酒店id查询酒店信息
        ItripHotel hotel=itripHotelMapper.getItripHotelById(vo.getHotelId());

        //根据房间id获取房间信息
        ItripHotelRoom room = itripHotelRoomMapper.getItripHotelRoomById(vo.getRoomId());


        //封装前端需要的实体类
        RoomStoreVO roomStoreVO=new RoomStoreVO();
        roomStoreVO.setCheckInDate(vo.getCheckInDate());
        roomStoreVO.setCheckOutDate(vo.getCheckOutDate());
        roomStoreVO.setCount(vo.getCount());
        roomStoreVO.setHotelId(hotel.getId());
        roomStoreVO.setHotelName(hotel.getHotelName());
        roomStoreVO.setRoomId(room.getId());
        roomStoreVO.setPrice(BigDecimal.valueOf(room.getRoomPrice()));

        //封装查询参数
        HashMap<String,Object> param = new HashMap();
        param.put("startTime",vo.getCheckInDate());
        param.put("endTime",vo.getCheckOutDate());
        param.put("roomId",vo.getRoomId());
        param.put("hotelId",vo.getHotelId());

        //计算库存
        List<ItripHotelTempStore> stores=queryRoomStore(param);
        if (!EmptyUtils.isNotEmpty(stores)) {
            return DtoUtil.returnFail("暂时无房","100512");
        }else{
            roomStoreVO.setStore(stores.get(0).getStore());
            return DtoUtil.returnSuccess("获取成功",roomStoreVO);
        }
    }


    /**
     * 修改日期校验库存
     * @param vo
     * @return
     * @throws Exception
     */
    @Override
    public Dto getValiDateRoomStore1(ValidateRoomStoreVO vo) throws Exception {
        //封装查询参数
        HashMap<String,Object> param=new HashMap();
        param.put("startTime",vo.getCheckInDate());
        param.put("endTime",vo.getCheckOutDate());
        param.put("roomId",vo.getRoomId());
        param.put("hotelId",vo.getHotelId());
        //计算最小库存
        List<ItripHotelTempStore> stores=queryRoomStore(param);

        Map<String,Object> output=new HashMap<>();

        if (!EmptyUtils.isNotEmpty(stores)) {
                output.put("flag",false);
                output.put("store",0);
        }else {
            output.put("flag",stores.get(0).getStore()>=vo.getCount());
            output.put("store",stores.get(0).getStore());
        }
        return DtoUtil.returnDataSuccess(output);
    }


    /**
     * 计算库存
     * @param param
     * @return
     * @throws Exception
     */
    @Override
    public List<ItripHotelTempStore> queryRoomStore(HashMap<String, Object> param) throws Exception {

        //调用存储过程，刷新实时库存表
        itripHotelOrderMapper.flushRoomStore(param);

        //计算库存：实时库存表的库存数量-当日订单中对应该房型未支付的订单所占的库存
        List<ItripHotelTempStore> tempStores = itripHotelOrderMapper.queryRoomStore(param);

        return tempStores;
    }
}
